package InterconectionSubsystem;

import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import Config.ConfigReader;

import isDim.DynamicInterconectionManager;
import isDim.LocalConfig;
import isDim.dimCargo;
import isEs.EstimationExchanger;
import isEv.EventExchanger;
import isMonitor.InternalProcessMonitor;

public class Launcher {
	
	private static final int SQL_ERROR = 10;
	private static final int CONFIG_ERROR = 11;
	private static final int LOCALIP_ERROR = 12;

	public static void main(String[] args) {
		try{
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		}catch(Exception e){ System.out.println("FATAL ERROR. Error initializing sql driver: " + e.getMessage()); System.exit(SQL_ERROR); }

		int EstimationExchanger_subscriptionBusSubscriptionPort = 0, EstimationExchanger_busToSendEstimationsPort = 0;
		int EstimationExchanger_busListeningPort = 0, EstimationExchanger_airportsListeningPort = 0;
		int EventExchanger_busListeningPort = 0, EventExchanger_subscriptionBusSubscriptionPort =0;
		int EventExchanger_subscriptionBusNumeratedPort = 0, EventExchanger_airportsListeningPort = 0;
		int DynamicInterconectionManager_ListeningPort = 0, AirportCoordination_ListeningPort = 0;
		String EstimationExchanger_subscriptionBusHost = null, EstimationExchanger_busToSendEstimationsHost = null, EventExchanger_busListeningHost = null;
		String EventExchanger_subscriptionBusHost = null, AirportCoordination_Host = null, SystemwideDatabase_Host = null;
		String SystemwideDatabase_Database = null, SystemwideDatabase_Username = null, SystemwideDatabase_Password = null, SystemwideDatabase_dimDatabase = null;
		
		BlockingQueue<List<Address>> evBox = new LinkedBlockingQueue<List<Address>>();
		BlockingQueue<List<Address>> esBox = new LinkedBlockingQueue<List<Address>>();
		BlockingQueue<dimCargo> dimBox = new LinkedBlockingQueue<dimCargo>();
		BlockingQueue<Boolean> dimPong = new LinkedBlockingQueue<Boolean>();
		
		InetAddress localhost = null;
		try{ localhost = InetAddress.getLocalHost(); }catch(Exception e){ System.out.println("Error getting localhost ip: " + e.getMessage()); System.exit(LOCALIP_ERROR); }

		try{
			EstimationExchanger_subscriptionBusSubscriptionPort = ConfigReader.getInt("EstimationExchanger_subscriptionBusSubscriptionPort"); 
			EstimationExchanger_subscriptionBusHost = ConfigReader.getString("EstimationExchanger_subscriptionBusHost");
			EstimationExchanger_airportsListeningPort = ConfigReader.getInt("EstimationExchanger_airportsListeningPort");
			EstimationExchanger_busToSendEstimationsHost = ConfigReader.getString("EstimationExchanger_busToSendEstimationsHost");
			EstimationExchanger_busToSendEstimationsPort = ConfigReader.getInt("EstimationExchanger_busToSendEstimationsPort");
			EstimationExchanger_busListeningPort = ConfigReader.getInt("EstimationExchanger_busListeningPort");


			EventExchanger_busListeningPort = ConfigReader.getInt("EventExchanger_busListeningPort");
			EventExchanger_busListeningHost = ConfigReader.getString("EventExchanger_busListeningHost");
			EventExchanger_subscriptionBusSubscriptionPort = ConfigReader.getInt("EventExchanger_subscriptionBusSubscriptionPort");
			EventExchanger_subscriptionBusNumeratedPort = ConfigReader.getInt("EventExchanger_subscriptionBusNumeratedPort");
			EventExchanger_subscriptionBusHost = ConfigReader.getString("EventExchanger_subscriptionBusHost");
			EventExchanger_airportsListeningPort = ConfigReader.getInt("EventExchanger_airportsListeningPort");

			DynamicInterconectionManager_ListeningPort = ConfigReader.getInt("DynamicInterconectionManager_ListeningPort");
			AirportCoordination_ListeningPort = ConfigReader.getInt("AirportCoordination_ListeningPort");
			AirportCoordination_Host = ConfigReader.getString("AirportCoordination_Host");
			SystemwideDatabase_Host = ConfigReader.getString("SystemwideDatabase_Host");
			SystemwideDatabase_Database = ConfigReader.getString("SystemwideDatabase_Database");
			SystemwideDatabase_Username = ConfigReader.getString("SystemwideDatabase_Username");
			SystemwideDatabase_Password = ConfigReader.getString("SystemwideDatabase_Password");
			if (ConfigReader.has("Debug_LocalIp")) localhost = InetAddress.getByName(ConfigReader.getString("Debug_LocalIp"));
		}
		catch (Exception ex) {
            System.out.println("Error reading configuration: " + ex.getMessage());
            System.exit(CONFIG_ERROR);
        }
		
		LocalConfig lc = new LocalConfig(Sender.toString(localhost), DynamicInterconectionManager_ListeningPort, EventExchanger_airportsListeningPort, EstimationExchanger_airportsListeningPort,
				AirportCoordination_Host, AirportCoordination_ListeningPort, SystemwideDatabase_Host, SystemwideDatabase_Database, SystemwideDatabase_Username, SystemwideDatabase_Password);

		Thread dim = new Thread(new DynamicInterconectionManager(dimBox, evBox, esBox, dimPong, lc));
		Thread ipm = new Thread(new InternalProcessMonitor(dimBox, dimPong));
		Thread esx = new Thread(new EstimationExchanger(dimBox, esBox));
		Thread evex = new Thread(new EventExchanger(dimBox, evBox));
		
		// inicia  Event Exchanger
		evex.start();
		
		// inicia Estimation Exchanger
		esx.start();
		
		// inicia Dynamic Interconection Manager
		dim.start();
		
		// inicia Internal Process Monitor
		ipm.start();
	}
}
